<template>
  <div class="map__container">
    <div class="map__container" id="map-panel"></div>
    <!--        <div class="map_operation_top__container">-->
    <!--            <lay-button size="sm">返回</lay-button>-->
    <!--        </div>-->
    <!--        <div ref="compass" class="compass__container" @click="resetRotation">-->
    <!--            <div ref="compass_1">北</div>-->
    <!--            <div style="flex-direction: row; width: auto; background: unset;">-->
    <!--                <div ref="compass_2">西</div>-->
    <!--                <div ref="compass_5">＋</div>-->
    <!--                <div ref="compass_3">东</div>-->
    <!--            </div>-->
    <!--            <div ref="compass_4">南</div>-->
    <!--        </div>-->
    <div ref="compass" @click="resetRotation" class="icon-compass"></div>
    <div
      ref="checkBtn"
      style="
        padding: 5px 15px;
        background: rgba(71, 123, 226, 1);
        color: #fbfbfb;
        border-radius: 5px;
      "
      @click="endDraw"
    >
      结束
    </div>

    <div
      class="selected_area__container"
      style="display: flex; flex-wrap: wrap"
      v-if="Object.keys(selected).length > 0"
    >
      <template v-for="(v, k) in selected" :key="k">
        <div class="my-badge">
          <div class="badge__text">
            {{ v.name }} {{ v.describe ? " - " + v.describe : "" }}
          </div>
          <div class="badge__remove" @click="removeSelected(k)">X</div>
        </div>
      </template>
    </div>

    <div
      style="
        position: fixed;
        right: 2vw;
        bottom: 120px;
        display: flex;
        flex-direction: column;
        z-index: 1001;
      "
    >
      <div
        class="map-icon-btn icon-draw"
        title="绘制"
        v-if="!isDraw"
        @click="onDraw"
      ></div>
      <div
        class="map-icon-btn icon-draw-f"
        title="取消绘制"
        v-if="isDraw"
        @click="onCancelDoS"
      ></div>
      <div class="map-icon-btn icon-union" title="合并" @click="onUnion"></div>
      <div
        class="map-icon-btn icon-cut"
        title="拆分"
        v-if="!isSplit"
        @click="onSplit"
      ></div>
      <div
        class="map-icon-btn icon-cut-f"
        title="取消拆分"
        v-if="isSplit"
        @click="onCancelDoS"
      ></div>
      <div class="map-icon-btn icon-reset" title="重置" @click="onReset"></div>
      <div class="map-icon-btn icon-back" title="返回" @click="onBack"></div>
      <div
        class="map-icon-btn"
        :class="
          Object.keys(selected).length > 0 ? 'icon-right-f' : 'icon-right'
        "
        title="确认"
        @click="onSubmit()"
      ></div>
      <!--                <div class="map-icon-btn icon-right-f" title="确认" v-if="Object.keys(selected).length > 0" @click="onSubmit"></div>-->

      <!--                <lay-button class="oc__btn" size="sm" @click="onUnion()">合并</lay-button>-->
      <!--                <lay-button class="oc__btn" size="sm" @click="onSplit()" v-if="!isSplit">拆分</lay-button>-->
      <!--                <lay-button class="oc__btn" size="sm" @click="onCancelDoS()" v-if="isSplit">-->
      <!--                    取消拆分-->
      <!--                </lay-button>-->
      <!--                <lay-button class="oc__btn" size="sm" @click="onDraw()" v-if="!isDraw">绘制</lay-button>-->
      <!--                <lay-button class="oc__btn" size="sm" @click="onCancelDoS()" v-if="isDraw">-->
      <!--                    取消绘制-->
      <!--                </lay-button>-->
      <!--                <lay-button class="oc__btn" size="sm" @click="onReset()">重置</lay-button>-->
      <!--                <lay-button class="oc__btn" size="sm" @click="onBack()">返回</lay-button>-->
    </div>
    <!--            <div class="button__container" v-if="Object.keys(selected).length > 0">-->
    <!--                <lay-button size="sm" @click="canInsert = true">添加点</lay-button>-->
    <!--                <lay-button size="sm" @click="removePoint()">删除点</lay-button>-->
    <!--                <lay-button size="sm" @click="saveEdited()">保存</lay-button>-->
    <!--                <lay-button size="sm" @click="cancelEdited(true)">取消</lay-button>-->
    <!--                <lay-button size="sm" @click="onSubmit">保存</lay-button>-->
    <!--            </div>-->
    <div id="named__container">
      <van-popup :show="showPop" round style="width: 80%; height: 150px">
        <div style="padding: 15px 10px">
          <div>
            {{ need === "name" ? "名称" : "" }}
            {{ need === "describe" ? "区位描述" : "" }}
            :
          </div>
          <div style="margin-top: 5px">
            <van-cell-group>
              <van-field v-model="editDescribe" label="描述" placeholder="请输入描述" />
            </van-cell-group>
          </div>
        </div>
        <div style="text-align: right; padding-right: 20px">
          <van-button size="small" type="primary" @click="onSubmitDescribe">确认</van-button>
          <van-button size="small"  @click="onCancel">取消</van-button>
        </div>
      </van-popup>
    </div>
  </div>
</template>

<script>
import Map from "ol/Map";
import View from "ol/View";
import * as olControl from "ol/control";
import * as olLayer from "ol/layer";
import * as olSource from "ol/source";
import * as olStyle from "ol/style";
import * as olFormat from "ol/format";
import * as olInteraction from "ol/interaction";
import { Overlay as olOverlay } from "ol";
import Feature from "ol/Feature";
import * as olGeom from "ol/geom";
import TileGrid from "ol/tilegrid/TileGrid";
import { inAndOut } from "ol/easing";
import {
  FeatureService,
  MapService,
  TileSuperMapRest,
  SecurityManager,
  GetFeaturesBySQLParameters
} from "@supermap/iclient-ol";
import * as turf from "@turf/turf";
// import { SaveGoodsPosition, GetGoodsPosition } from "@/api/work-shift";
import DragPan from "ol/interaction/DragPan";
import { showFailToast } from "vant";
import { GetGoodsPosition, SubmitGoodsPosition } from "@/api/tally";

export default {
  name: "yard-map-v2",
  props: {
    positionInfo: Object,
    goodsPositionId: String
  },
  data() {
    return {
      isEdit: false,
      canInsert: false,
      loadFailedTimes: 0,
      selected: {},
      // featureService: new FeatureService('http://10.10.21.50:8090/iserver/services/data-SGSZTSJV20230315/rest/data'),
      featureService: null,
      gsonFormat: new olFormat.GeoJSON(),
      editKey: "",
      editDescribe: "",
      showPop: false,
      isDraw: false,
      isSplit: false,
      clickTimes: 0
    };
  },
  setup() {
    return {};
  },
  mounted: function () {
    this.initMap();
  },
  beforeUnmount() {
    document.getElementById("map-panel").innerHTML = "";
  },
  methods: {
    initMap() {
      console.log(this.positionInfo);
      if (this.loadFailedTimes >= 3) {
        return;
      }
      const url =
        "https://gis.tjgsgs.com/iserver/services/map-mongodb-TJVMapvGDWZ/rest/maps/TJVMap_vGDWZ";
      const yardUrl =
        "https://gis.tjgsgs.com/iserver/services/map-SGSZTSJVnet/rest/maps/SGSZTSJ";
      const dataUrl =
        "https://gis.tjgsgs.com/iserver/services/data-SGSZTSJVnet/rest/data";
      const key =
        "dUA7OmWhzxpMZKcOqeUd8Z3611FdQcVEpRV8V4GBDRDGg0zRf_z50xYulk_he2WEc5P9PApu9Nd-sAVa4w-PEQ";

      SecurityManager.registerToken(url, key);
      SecurityManager.registerToken(yardUrl, key);
      SecurityManager.registerToken(dataUrl, key);
      this.featureService = new FeatureService(dataUrl);
      new MapService(url).getMapInfo(serviceResult => {
        if (serviceResult.type === "processFailed") {
          this.loadFailedTimes = this.loadFailedTimes + 1;
          setTimeout(() => {
            this.initMap();
          }, 800);
          return;
        }
        const baseMapInfo = serviceResult.result;

        const resolutions = [];
        const visibleScales = [...baseMapInfo.visibleScales, 0.005, 0.01];
        visibleScales.forEach(i => {
          resolutions.push(
            (360 * 0.0254) /
              (baseMapInfo.dpi *
                2 *
                Math.PI *
                baseMapInfo.prjCoordSys.coordSystem.datum.spheroid.axis) /
              i
          );
        });
        this.resolutions = resolutions;

        const baseMap = this.initLayer(url, baseMapInfo, resolutions);
        const yardMap = this.initLayer(yardUrl, baseMapInfo, resolutions);

        const view = new View({ projection: "EPSG:4326" });

        this.checkOberlay = new olOverlay({
          element: this.$refs.checkBtn,
          autoPan: true,
          autoPanAnimation: {
            duration: 250
          },
          offset: [20, 20]
        });

        this.map = new Map({
          target: document.getElementById("map-panel"),
          controls: olControl.defaults({
            zoom: false,
            rotate: false,
            attribution: false
          }),
          layers: [baseMap, yardMap],
          view,
          overlays: [this.checkOberlay]
        });

        this.areaLayer = new olLayer.Vector({
          source: new olSource.Vector(),
          zIndex: 100,
          style: feature => {
            const name = feature.get("QWMC");
            const describe = feature.get("describe");
            const selected = feature.get("selected");
            const canReset = feature.get("canReset");
            return new olStyle.Style({
              zIndex: selected === 1 ? 100 : 99,
              fill: new olStyle.Fill({
                color:
                  selected === 1
                    ? "rgba(224, 254, 239, .7)"
                    : "rgba(226, 236, 249, .7)"
              }),
              stroke: new olStyle.Stroke({
                color:
                  selected === 1
                    ? "rgba(100, 216, 137, .7)"
                    : "rgba(71, 123, 226, .7)",
                width: 3
              }),
              text: new olStyle.Text({
                font: "14px Calibri,sans-serif",
                fill: new olStyle.Fill({
                  color: "#000"
                }),
                text:
                  (canReset !== 1 ? name : "") +
                  (describe ? " - " + describe : ""),
                stroke: new olStyle.Stroke({
                  color: "#fbfbfb",
                  width: 3
                })
              })
            });
          }
        });
        this.map.addLayer(this.areaLayer);

        this.yardLayer = new olLayer.Vector({
          source: new olSource.Vector(),
          style: new olStyle.Style()
        });
        this.map.addLayer(this.yardLayer);

        this.getYard();
        this.getArea();

        this.edistLayer = new olLayer.Vector({
          source: new olSource.Vector(),
          zIndex: 101,
          style: [
            new olStyle.Style({
              stroke: new olStyle.Stroke({
                width: 5,
                color: "rgb(221, 109, 44, 1)",
                lineDash: [10, 15]
              }),
              fill: new olStyle.Fill({
                color: "rgba(250, 231, 217, 1)"
              }),
              image: new olStyle.Circle({
                stroke: new olStyle.Stroke({
                  color: "rgba(250, 231, 217, 1)",
                  width: 3
                }),
                fill: new olStyle.Fill({
                  color: "rgb(221, 109, 44, 1)"
                }),
                radius: 8
              })
            }),
            new olStyle.Style({
              image: new olStyle.Circle({
                stroke: new olStyle.Stroke({
                  color: "#FFF",
                  width: 3
                }),
                fill: new olStyle.Fill({
                  color: "rgb(238, 125, 49)"
                }),
                radius: 8
              }),
              stroke: new olStyle.Stroke({
                width: 5,
                color: "rgb(238, 125, 49)",
                lineDash: [10, 15]
              }),
              fill: new olStyle.Fill({
                color: "rgba(255, 255, 255, 0.5)"
              }),
              geometry: f => {
                if (f.getGeometry() instanceof olGeom.MultiPolygon) {
                  const coordinates = f.getGeometry().getCoordinates()[0][0];
                  return new olGeom.MultiPoint(coordinates);
                }
              }
            })
          ]
        });
        this.map.addLayer(this.edistLayer);

        this.tempLayer = new olLayer.Vector({
          source: new olSource.Vector(),
          zIndex: 111,
          style: f => {
            return new olStyle.Style({
              image: new olStyle.Circle({
                stroke: new olStyle.Stroke({
                  color: "#FFF",
                  width: 6
                }),
                fill: new olStyle.Fill({
                  color: "rgb(238, 125, 49)"
                }),
                radius: 11
              }),
              stroke: new olStyle.Stroke({
                width: 8,
                color: "#" + f.get("rColor")
              }),
              fill: new olStyle.Fill({
                color: "rgba(255, 255, 255, 0.5)"
              })
            });
          }
        });

        this.map.addLayer(this.tempLayer);

        this.sPointLayer = new olLayer.Vector({
          source: new olSource.Vector(),
          zIndex: 102,
          style: new olStyle.Style({
            image: new olStyle.Circle({
              stroke: new olStyle.Stroke({
                color: "rgba(255, 0, 0, 1)",
                width: 3
              }),
              radius: 10
            })
          })
        });
        this.map.addLayer(this.sPointLayer);

        this.map.once("loadend", () => {
          // 添加点击事件
          this.map.on("singleclick", e => {
            if (this.isDraw || this.isSplit) {
              this.clickTimes++;
              if (this.isDraw && this.clickTimes > 2) {
                this.checkOberlay.setPosition(e.coordinate);
              }
              if (this.isSplit && this.clickTimes > 1) {
                this.checkOberlay.setPosition(e.coordinate);
              }
              return;
            }
            const selectedAreas = this.map.getFeaturesAtPixel(e.pixel, {
              hitTolerance: 10,
              layerFilter: e => {
                return e === this.areaLayer;
              }
            });

            // if (this.isEdit) {
            //     if (selectedAreas && selectedAreas.length > 0) {
            //         this.sPointLayer.setSource(new olSource.Vector({
            //             features: [new Feature({
            //                 geometry: new olGeom.Point(this.tempPoint)
            //             })],
            //             wrapX: false,
            //         }))
            //     } else {
            //         this.sPointLayer.setSource(new olSource.Vector())
            //     }
            //     return
            // }

            if (selectedAreas && selectedAreas.length > 0) {
              const fs = selectedAreas[0];
              const smId = fs.get("SMID");
              if (Object.prototype.hasOwnProperty.call(this.selected, smId)) {
                if (fs.get("canReset") === 1) {
                  this.manmoryF = fs;
                  this.areaLayer.getSource().removeFeature(fs);
                }
                this.removeSelected(smId);
                // const f = this.simplify24Point(fs)
                // this.edistLayer.setSource(new olSource.Vector({
                //     features: [this.gsonFormat.readFeature(f)],
                // }))
                // this.onModify()
                return;
              }
            }

            selectedAreas.forEach((i, ii) => {
              const smId = i.get("SMID");
              const name = i.get("QWMC");
              const geometry = i.get("geometry");

              this.selected[smId] = {
                name,
                geometry,
                features: [i]
              };
              i.set("selected", 1);

              if (i.get("needDescribe") === 1) {
                this.editKey = smId;
                this.showPop = true;
                this.need = "describe";
                return;
              }
              if (i.get("needNamed") === 1) {
                this.editKey = smId;
                this.showPop = true;
                this.need = "name";
                return;
              }
            });
          });

          setTimeout(() => {
            if (this.goodsPositionId) {
              console.log(this.goodsPositionId, 'googdsssss');
              GetGoodsPosition({id: this.goodsPositionId}).then(res => {
                console.log(res.data);
                const sd = JSON.parse(res.data);
                const fs = [];
                for (let sdKey in sd) {
                  const d = sd[sdKey];
                  const g = d.geometry;
                  const rg = this.gsonFormat.readGeometry(g);
                  fs.push(
                    new Feature({
                      geometry: rg,
                      QWMC: d.name,
                      describe: d.describe,
                      SMID: sdKey.split("-")[0],
                      selected: 1
                    })
                  );
                }

                const vectorSource = new olSource.Vector({
                  features: fs,
                  wrapX: false
                });

                this.areaLayer.setSource(vectorSource);
              });
            }
          });
        });
      });
    },
    onReset() {
      this.selected = {};
      this.getArea();
    },
    resetRotation() {
      this.map.getView().animate({ rotation: 0 });
    },
    onBack() {
      this.$emit("closeMap");
    },
    onCancel() {
      this.showPop = false;
      this.editKey = false;
      this.editDescribe = "";
    },
    onCancelDoS() {
      this.checkOberlay.setPosition(null);
      this.clickTimes = 0;
      if (this.interactionDraw) {
        this.map.removeInteraction(this.interactionDraw);
        this.isDraw = false;
      }
      if (this.draw) {
        this.map.removeInteraction(this.draw);
        this.isSplit = false;
      }
    },
    endDraw() {
      if (this.interactionDraw) {
        this.interactionDraw.finishDrawing();
      }
      if (this.draw) {
        this.draw.finishDrawing();
      }
      this.checkOberlay.setPosition(null);
      this.onCancelDoS();
    },
    onDraw() {
      this.isDraw = true;
      if (this.interactionDraw) {
        this.map.removeInteraction(this.interactionDraw);
      }
      this.interactionDraw = new olInteraction.Draw({
        source: this.areaLayer.getSource(),
        style: new olStyle.Style({
          stroke: new olStyle.Stroke({
            width: 5,
            color: "rgb(221, 109, 44, 1)",
            lineDash: [10, 15]
          }),
          fill: new olStyle.Fill({
            color: "rgba(250, 231, 217, 1)"
          }),
          image: new olStyle.Circle({
            stroke: new olStyle.Stroke({
              color: "rgba(250, 231, 217, 1)",
              width: 3
            }),
            fill: new olStyle.Fill({
              color: "rgb(221, 109, 44, 1)"
            }),
            radius: 8
          })
        }),
        type: "Polygon"
      });

      this.interactionDraw.on("drawend", e => {
        this.onCancelDoS();
        this.isDraw = false;
        const ft = e.feature;
        const smid = new Date().getTime();

        ft.set("SMID", smid);
        ft.set("QWMC", "");
        ft.set("needNamed", 1);

        this.map.removeInteraction(this.interactionDraw);
      });
      this.map.addInteraction(this.interactionDraw);
    },
    onSubmit() {
      // saveGoodsPosition
      if (Object.keys(this.selected).length === 0) {
        return;
      }
      const area = Object.keys(this.selected).join();
      const yard = this.positionInfo.code;
      const names = [];
      const jsonData = {};
      for (let selectedKey in this.selected) {
        const sd = this.selected[selectedKey];
        names.push(sd.name + (sd.describe ? "-" + sd.describe : ""));

        jsonData[selectedKey] = {
          name: sd.name,
          describe: sd.describe,
          geometry: this.gsonFormat.writeGeometry(sd.geometry)
        };
      }

      SubmitGoodsPosition({
        jsonData: JSON.stringify(jsonData),
        storageId: "",
        yardCode: yard,
        areaCode: area
      }).then(res => {
        this.$emit("saved", {
          id: res.data,
          names: names.join()
        });
      });
    },
    onSubmitDescribe() {
      if (this.editDescribe) {
        if (this.need === "name") {
          this.selected[this.editKey].name = this.editDescribe;
          this.selected[this.editKey].features[0].set(
            "QWMC",
            this.editDescribe
          );
        } else if (this.need === "describe") {
          this.selected[this.editKey].describe = this.editDescribe;
          this.selected[this.editKey].features[0].set(
            "describe",
            this.editDescribe
          );
        }
      }
      this.onCancel();
    },
    simplify24Point(feature, tolerance = 100) {
      const options = { tolerance, highQuality: true };
      const gos = this.gsonFormat.writeFeatureObject(feature);
      const simplified = turf.simplify(gos, options);
      if (simplified.geometry.coordinates[0][0].length < 5) {
        tolerance = tolerance / 10;
        return this.simplify24Point(feature, tolerance);
      }
      return simplified;
    },
    getArea() {
      const sql = "CKBH = '" + this.positionInfo.code + "'";

      const queryParams = new GetFeaturesBySQLParameters({
        queryParameter: {
          name: "SGSZTSJ@区位",
          attributeFilter: sql
        },
        datasetNames: ["SGSZTSJ:区位"],
        toIndex: -1,
        maxFeatures: -1
      });

      this.featureService.getFeaturesBySQL(queryParams, res => {
        if (res.error || res.result.featureCount === 0) {
          showFailToast("区位异常，请联系管理员");
          this.onBack();
          return;
        }

        if (res.result.features) {
          const vectorSource = new olSource.Vector({
            features: new olFormat.GeoJSON().readFeatures(res.result.features),
            wrapX: false
          });

          this.areaLayer.setSource(vectorSource);
        }
      });
    },
    getYard() {
      const sql = "CKBH = '" + this.positionInfo.code + "'";

      const queryParams = new GetFeaturesBySQLParameters({
        queryParameter: {
          name: "SGSZTSJ@堆场场位",
          attributeFilter: sql
        },
        datasetNames: ["SGSZTSJ:堆场场位"],
        toIndex: -1,
        maxFeatures: -1
      });

      this.featureService.getFeaturesBySQL(queryParams, res => {
        if (res.error || res.result.featureCount === 0) {
          showFailToast("场位异常，请联系管理员");
          this.onBack();
          return;
        }

        if (res.result.features) {
          const vectorSource = new olSource.Vector({
            features: new olFormat.GeoJSON().readFeatures(res.result.features),
            wrapX: false
          });

          this.yardLayer.setSource(vectorSource);
          this.fixExtent(vectorSource.getExtent());
        }
      });
    },
    onModify: function () {
      this.isEdit = true;
      this.interactionModify = new olInteraction.Modify({
        source: this.edistLayer.getSource(),
        insertVertexCondition: () => {
          if (this.canInsert) {
            this.canInsert = false;
            return true;
          }
          return false;
        },
        style: a => {
          this.tempPoint = a.get("geometry").flatCoordinates;
          this.sPointLayer.setSource(
            new olSource.Vector({
              features: [
                new Feature({
                  geometry: new olGeom.Point(this.tempPoint)
                })
              ],
              wrapX: false
            })
          );
        }
      });

      this.map.addInteraction(this.interactionModify);
    },
    fixExtent(extent) {
      const view = this.map.getView();
      view.fit(extent, {
        size: this.map.getSize(),
        padding: [200, 200, 200, 200],
        easing: inAndOut
      });

      const newExtent = view.calculateExtent();
      const projection = view.get("projection");
      const resolutions = view.get("resolutions");
      const new_view = new View({
        resolutions,
        projection,
        extent: newExtent
      });

      new_view.on("change:rotation", e => {
        const deg = e.oldValue * (180 / Math.PI);
        this.$refs.compass.style.transform = "rotate(" + deg + "deg)";
        // this.$refs.compass_1.style.transform = 'rotate(' + -deg + 'deg)';
        // this.$refs.compass_2.style.transform = 'rotate(' + -deg + 'deg)';
        // this.$refs.compass_3.style.transform = 'rotate(' + -deg + 'deg)';
        // this.$refs.compass_4.style.transform = 'rotate(' + -deg + 'deg)';
        // this.$refs.compass_5.style.transform = 'rotate(' + -deg + 'deg)';
      });

      new_view.fit(extent, {
        size: this.map.getSize(),
        padding: [150, 150, 150, 150]
      });

      if (!this.resetView) {
        this.resetView = new_view;
      }

      this.map.setView(new_view);
    },
    removePoint() {
      this.interactionModify.removePoint();
      this.sPointLayer.setSource(new olSource.Vector());
    },
    saveEdited() {
      const fs = this.edistLayer.getSource().getFeatures();
      const areaSource = this.areaLayer.getSource();
      fs.forEach(i => {
        const f = i.clone();
        f.set("canReset", 1);
        const smId = f.get("SMID");
        this.selected[smId].features.push(f);
        areaSource.addFeature(f);
      });
      this.cancelEdited();
    },
    cancelEdited(reset = false) {
      this.isEdit = false;
      this.map.removeInteraction(this.interactionModify);
      this.edistLayer.setSource(new olSource.Vector());
      this.sPointLayer.setSource(new olSource.Vector());
      this.interactionModify = null;
      if (reset && this.manmoryF) {
        this.areaLayer.getSource().addFeature(this.manmoryF);
        this.manmoryF = null;
      }
    },
    initLayer(url, mapInfo, resolutions) {
      return new olLayer.Tile({
        source: new TileSuperMapRest({
          url: url,
          prjCoordSys: { epsgCode: 4326 },
          clipRegionEnabled: true,
          format: "webp",
          crossOrigin: "anonymous",
          tileGrid: new TileGrid({
            extent: [
              mapInfo.bounds.left,
              mapInfo.bounds.bottom,
              mapInfo.bounds.right,
              mapInfo.bounds.top
            ],
            resolutions
          })
        })
      });
    },
    removeSelected(key) {
      const areaSource = this.areaLayer.getSource();
      this.selected[key].features.forEach(i => {
        i.set("selected", 0);
        const canReset = i.get("canReset");
        if (canReset === 1) {
          areaSource.removeFeature(i);
        }
      });
      delete this.selected[key];
    },
    unionAll(ls, res) {
      const ls2 = [];
      let index = 0;
      if (!res) {
        res = ls[0];
        index = 1;
      }
      for (let i = index; i < ls.length; i++) {
        if (turf.lineIntersect(res, ls[i])) {
          res = turf.union(res, ls[i]);
        } else {
          ls2.push(ls[i]);
        }
      }

      if (ls2.length === 0 || ls.length === ls2.length) {
        return res;
      }
      return this.unionAll(ls2, res);
    },
    onUnion() {
      const array = [];
      const names = new Set();
      const smids = new Set();
      for (const selectedKey in this.selected) {
        const ft = this.selected[selectedKey];
        const a = this.gsonFormat.writeGeometryObject(ft.geometry);
        let ps = [];
        if (a.type === "Polygon") {
          array.push(turf.polygon(a.coordinates));
        } else if (a.type === "MultiPolygon") {
          a.coordinates.forEach(i => {
            array.push(turf.polygon(i));
          });
        }

        // ps.forEach(i => {
        // const buffered = turf.buffer(i, 0.0005, {steps: 1});
        // array.push(buffered);
        // })
        // const buffered = turf.buffer(turf.polygon(a.coordinates[0]), 0.0005, {steps: 1});
        // array.push(buffered);
        // array.push(turf.polygon(a.coordinates[0]))
        const ns = ft.name.split("-");
        const sk = selectedKey.split("-");

        smids.add(sk[0]);
        names.add(ns[0]);
      }

      let ufs = this.unionAll(array);

      const smId = Array.from(smids).join();
      const name = Array.from(names).join();
      let ug = ufs.geometry;

      let geometry;
      if (ug.type === "Polygon") {
        geometry = new olGeom.Polygon(ug.coordinates);
      } else if (ug.type === "MultiPolygon") {
        geometry = new olGeom.MultiPolygon(ug.coordinates);
      }

      const ft = new Feature({
        geometry,
        QWMC: name,
        SMID: smId,
        selected: 1
      });

      for (let selectedKey in this.selected) {
        this.removeSelected(selectedKey);
      }

      this.selected[smId] = {
        name,
        geometry,
        features: [ft]
      };

      const vectorSource = new olSource.Vector({
        features: [ft],
        wrapX: false
      });

      this.areaLayer.setSource(vectorSource);
    },
    _lineSplitByPoint(points, polygon) {
      const lines = [];
      for (let i = 0; i < points.length; i++) {
        const all_lines = [];
        for (let j = i + 1; j < points.length; j++) {
          all_lines.push({
            i: i,
            j: j,
            d:
              turf.rhumbDistance(turf.point(points[i]), points[j]) *
              Math.pow(10, 7)
          });
        }

        const sort_lines = all_lines.sort((a, b) => a.d - b.d);
        const t_array = sort_lines.filter(i => i.i === 0).map(i => i.j);
        for (let j = 0; j < t_array.length; j++) {
          if (t_array[j] - t_array[j + 1] > 0) {
            const l = [];
            l.push(points[0]);
            t_array.forEach(item => {
              l.push(points[item]);
            });
            return this._lineSplitByPoint(l, polygon);
          }
        }

        if (sort_lines.length > 0) {
          const tl = sort_lines[0];
          lines.push([points[tl.i], points[tl.j]]);
        }
      }
      return lines;
    },
    onSplit() {
      if (Object.keys(this.selected).length === 0) {
        return;
      }

      let x = 0;
      let y = 0;
      let x1 = 0;
      let y1 = 0;

      for (let selectedKey in this.selected) {
        const f = this.selected[selectedKey].features[0];
        const bbox = f.getGeometry().getExtent();

        x = Math.max(x, bbox[0]);
        y = Math.max(y, bbox[1]);
        x1 = Math.max(x1, bbox[2]);
        y1 = Math.max(y1, bbox[3]);
      }

      const bbox = [x, y, x1, y1];

      this.fixExtent(bbox);

      let pan;
      this.map.getInteractions().forEach(element => {
        if (element instanceof DragPan) {
          pan = element;
        }
      });

      pan.setActive(false);

      this.isSplit = true;
      const drawingSource = new olSource.Vector({ wrapX: false });
      const drawingLayer = new olLayer.Vector({
        source: drawingSource
      });
      this.map.addLayer(drawingLayer);

      // 绘标图层
      this.draw = new olInteraction.Draw({
        source: drawingSource,
        type: "LineString",
        style: new olStyle.Style({
          stroke: new olStyle.Stroke({
            width: 5,
            color: "rgb(96,104,125, 1)",
            lineDash: [10, 15]
          }),
          fill: new olStyle.Fill({
            color: "rgba(250, 231, 217, 1)"
          }),
          image: new olStyle.Circle({
            stroke: new olStyle.Stroke({
              color: "rgb(96,104,125, 1)",
              width: 3
            }),
            fill: new olStyle.Fill({
              color: "rgba(250, 231, 217, 1)"
            }),
            radius: 8
          })
        })
      });

      this.draw.on("drawend", e => {
        this.onCancelDoS();
        this.isSplit = false;
        pan.setActive(true);
        this.map.removeLayer(drawingLayer);
        this.map.removeInteraction(this.draw);

        this.map.removeLayer(drawingLayer);
        this.map.removeInteraction(this.draw);
        this.map.setView(this.resetView);

        const coord = e.feature.getGeometry().flatCoordinates;

        const s_points = [];
        for (let i = 0; i < coord.length; i += 2) {
          s_points.push([coord[i], coord[i + 1]]);
        }

        const splitter = turf.lineString(s_points);

        const res = [];
        const fs = [];
        for (let selectedKey in this.selected) {
          const name = this.selected[selectedKey].name;
          const smId = selectedKey;

          const ft = this.selected[selectedKey];
          const a = this.gsonFormat.writeGeometryObject(ft.geometry);
          const coords = turf.coordAll(a);
          const polygon = turf.polygon([coords]);

          let sp_lines = [];
          const lines = [];
          const i_points = [];

          for (let i = 0; i < coords.length - 1; i++) {
            let sp_point = [];
            const p1 = coords[i];
            const p2 = coords[i + 1];

            const t_line = turf.lineString([p1, p2]);
            const li = turf.lineIntersect(t_line, splitter);

            li.features.forEach(item => {
              sp_point.push(item.geometry.coordinates);
              i_points.push(item.geometry.coordinates);
            });

            const spls = this._lineSplitByPoint([p1, ...sp_point, p2], polygon);

            if (spls.length > 0) {
              spls.forEach(i => {
                lines.push([i]);
              });
              sp_lines = [];
            } else {
              sp_lines.push([p1, p2]);
            }
          }

          let sp_lines2 = [];
          for (let i = 0; i < s_points.length - 1; i++) {
            let sp_point2 = [];
            const sp = turf.lineString([s_points[i], s_points[i + 1]]);
            for (let k = 0; k < i_points.length; k++) {
              const p = turf.point(i_points[k]);
              const p2ld = turf.pointToLineDistance(p, sp, {
                units: "degrees"
              });

              if (p2ld <= 0) {
                sp_point2.push(i_points[k]);
              }
            }

            const spls = this._lineSplitByPoint(
              [s_points[i], ...sp_point2, s_points[i + 1]],
              polygon
            );

            if (spls.length > 0) {
              spls.forEach(i => {
                lines.push([i]);
              });
              sp_lines2 = [];
            } else {
              sp_lines2.push([s_points[i], s_points[i + 1]]);
            }
          }
          lines.push(sp_lines2);
          lines.push(sp_lines);
          const mls = [];
          lines.forEach(i => {
            mls.push(turf.multiLineString(i));
          });

          const fc = turf.featureCollection([...mls]);
          const l2p = turf.polygonize(fc);
          l2p.features.forEach(item => {
            const pip = turf.intersect(item, polygon);
            if (pip) {
              res.push({
                smId,
                name,
                g: pip
              });
            }
          });

          this.removeSelected(selectedKey);
        }

        res.forEach((item, i) => {
          fs.push(
            new Feature({
              geometry: new olGeom.Polygon(item.g.geometry.coordinates),
              QWMC: item.name,
              SMID: item.smId + "-" + i,
              needDescribe: 1,
              describe: ""
              // rColor: Math.floor(Math.random() * 16777215).toString(16)
            })
          );
        });

        this.areaLayer.setSource(
          new olSource.Vector({
            features: fs,
            wrapX: false
          })
        );
      });

      this.map.addInteraction(this.draw);
    },
    onSplit3() {
      const drawingSource = new olSource.Vector({ wrapX: false });
      const drawingLayer = new olLayer.Vector({
        source: drawingSource
      });
      this.map.addLayer(drawingLayer);

      // 绘标图层
      this.draw = new olInteraction.Draw({
        source: drawingSource,
        type: "LineString",
        stopClick: true
      });

      this.draw.on("drawend", e => {
        this.map.removeLayer(drawingLayer);
        this.map.removeInteraction(this.draw);

        const coord = e.feature.getGeometry().flatCoordinates;

        const s_points = [];
        for (let i = 0; i < coord.length; i += 2) {
          s_points.push([coord[i], coord[i + 1]]);
        }

        const splitter = turf.lineString(s_points);

        for (let selectedKey in this.selected) {
          const ft = this.selected[selectedKey];

          const a = this.gsonFormat.writeGeometryObject(ft.geometry);

          const coords = turf.coordAll(a);

          const polygon = turf.polygon([coords]);
          const p2l = turf.polygonToLine(polygon);
          // const li = turf.lineIntersect(p2l, splitter);
          const ls = turf.lineSplit(p2l, splitter);
          const ls2 = turf.lineSplit(splitter, p2l);

          const unionLs = turf.featureCollection([
            ...ls.features,
            ...ls2.features
          ]);

          // const options = {precision: 7};
          const truncated = turf.truncate(unionLs);
          // const truncated = turf.truncate(unionLs, options);

          const l2p = turf.polygonize(truncated);

          const fs = [];

          l2p.features.forEach(i => {
            fs.push(
              new Feature({
                geometry: new olGeom.Polygon(i.geometry.coordinates),
                rColor: Math.floor(Math.random() * 16777215).toString(16)
              })
            );
          });

          this.tempLayer.setSource(
            new olSource.Vector({
              features: fs,
              wrapX: false
            })
          );
        }
      });

      this.map.addInteraction(this.draw);
    },
    onSplit2() {
      const drawingSource = new olSource.Vector({ wrapX: false });
      const drawingLayer = new olLayer.Vector({
        source: drawingSource
      });
      this.map.addLayer(drawingLayer);

      // 绘标图层
      this.draw = new olInteraction.Draw({
        source: drawingSource,
        type: "LineString",
        stopClick: true
      });

      let split_line = [];

      this.draw.on("drawend", e => {
        // this._clearDrawingBoard();
        const coord = e.feature.getGeometry().flatCoordinates;
        split_line = [
          [coord[0], coord[1]],
          [coord[2], coord[3]]
        ];

        const splitter = turf.lineString(split_line);

        for (let selectedKey in this.selected) {
          const ft = this.selected[selectedKey];

          const a = this.gsonFormat.writeGeometryObject(ft.geometry);
          const polygon = turf.polygon(a.coordinates[0]);
          const pg = polygon.geometry;
          const lines = turf.polygonToLine(pg);

          const split = turf.lineSplit(lines, splitter);

          const split2 = turf.lineSplit(splitter, lines);

          const win_fs = [];

          split2.features.forEach(i => {
            const win = turf.booleanWithin(i.geometry, pg);
            if (win) {
              win_fs.push(i);
            }
          });

          split.features.forEach(i => {
            const t = turf.truncate(i, { precision: 7 });
          });

          const fc = turf.featureCollection([
            ...split.features,
            ...split2.features,
            ...win_fs
            // split.features[2],
            // split.features[0],
            // ...win_fs,
          ]);

          const tc = turf.truncate(fc, { precision: 8 });

          const to_pg = turf.polygonize(tc);

          const fs = [];

          to_pg.features.forEach(i => {
            fs.push(
              new Feature({
                geometry: new olGeom.Polygon(i.geometry.coordinates)
              })
            );
          });

          // fc.features.forEach((i) => {
          //     fs.push(new Feature({
          //         geometry: new olGeom.LineString(i.geometry.coordinates)
          //     }))
          // })
          //
          // split2.features.forEach((i) => {
          //     fs.push(new Feature({
          //         geometry: new olGeom.LineString(i.geometry.coordinates)
          //     }))
          // })

          // split.features.forEach((i) => {
          //     const p = turf.lineIntersect(turf.lineString(i.geometry.coordinates), splitter);
          //     if (p.features[0]) {
          //         sl.push(p.features[0].geometry.coordinates)
          //     }
          //
          //     fs.push(turf.lineString(i.geometry.coordinates))
          // })

          // fs.push(turf.lineString(sl))
          //
          const vectorSource = new olSource.Vector({
            features: fs,
            wrapX: false
          });

          this.areaLayer.setSource(vectorSource);

          this.map.removeLayer(drawingLayer);
          this.map.removeInteraction(this.draw);
        }
      });

      this.map.addInteraction(this.draw);

      // for (let selectedKey in this.selected) {
      //     const ft = this.selected[selectedKey];
      //     const a = this.gsonFormat.writeGeometryObject(ft.geometry);
      //
      //     const lines = turf.polygonToLine(a);
      //     const ft_line = lines[0];
      //
      //
      //     var split = turf.lineSplit(ft_line, splitter);
      //
      // }
    }
  }
};
</script>

<style scoped lang="less">
.map__container {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1000;

  .oc__btn {
    background-color: #fbfbfb;
    margin: 10px 0 0 0;
  }

  .map_operation_top__container {
    position: fixed;
    top: 10px;
    right: 10px;
    background: rgba(255, 255, 255, 0.9);
  }

  .icon-union {
    background-image: url("../../assets/icon-map/union.svg");
  }

  .icon-cut {
    background-image: url("../../assets/icon-map/cut.svg");
  }

  .icon-cut-f {
    background-image: url("../../assets/icon-map/cut-s.svg");
  }

  .icon-draw {
    background-image: url("../../assets/icon-map/draw.svg");
  }

  .icon-draw-f {
    background-image: url("../../assets/icon-map/draw-s.svg");
  }

  .icon-reset {
    background-image: url("../../assets/icon-map/reset.svg");
  }

  .icon-back {
    background-image: url("../../assets/icon-map/back.svg");
  }

  .icon-right-f {
    background-image: url("../../assets/icon-map/right-s.svg");
  }

  .icon-right {
    background-image: url("../../assets/icon-map/right.svg");
  }

  .icon-compass {
    position: fixed;
    left: 30px;
    top: 60px;
    width: 40px;
    height: 40px;
    background-image: url("../../assets/icon-map/compass.svg");
    background-size: 100%;
  }

  .map-icon-btn {
    width: 36px;
    height: 36px;
    margin-top: 10px;
    background-color: #fff;
    background-position: center;
    background-size: 20px 20px;
    background-repeat: no-repeat;
    border-radius: 10px;
  }

  .selected_area__container {
    bottom: 10px;
    background-color: #fff;
    width: 90vw;
    display: flex;
    flex-wrap: wrap;
    position: fixed;
    left: 5vw;
    max-height: 100px;
    border-radius: 10px;
    overflow: scroll;
    padding: 5px 10px;
    z-index: 1001;
  }

  .compass__container {
    color: forestgreen;
    position: fixed;
    top: 20px;
    right: 20px;
    display: flex;
    flex-direction: column;
    align-items: center;

    div {
      width: 20px;
      height: 20px;
      background-color: rgba(255, 255, 255, 0.6);
      text-shadow: 1px 1px #999;
      border-radius: 100%;
      font-weight: 900;
      display: flex;
      flex-direction: column;
      align-items: center;
    }
  }

  .ol-popup {
    position: absolute;
    background-color: white;
    -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
    filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
    padding: 15px;
    border-radius: 10px;
    border: 1px solid #cccccc;
    bottom: 12px;
    left: -50px;
    min-width: 280px;
  }

  .ol-popup:after,
  .ol-popup:before {
    top: 100%;
    border: solid transparent;
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none;
  }

  .ol-popup:after {
    border-top-color: white;
    border-width: 10px;
    left: 48px;
    margin-left: -10px;
  }

  .ol-popup:before {
    border-top-color: #cccccc;
    border-width: 11px;
    left: 48px;
    margin-left: -11px;
  }

  .my-badge {
    display: flex;
    padding: 2px 10px;
    //border: 1px solid blue;
    border-radius: 5px;
    width: 30%;
    margin: 2px 5px;
    background-color: #eef1f3;

    .badge__text {
      width: 100%;
      text-align: center;
    }

    .badge__remove {
      text-align: center;
      //border-left: 1px dashed blue;
      padding: 2px 2px 2px 10px;
      color: #999;
    }
  }
}
</style>
